home *** CD-ROM | disk | FTP | other *** search
- ; DEBUGGER.S
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Scheme code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* System Debugger and Error Handlers *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: David Bartley Date: Oct 1985 *
- ;* Revision history: *
- ;* - 13 Mar 87: Extended errors for DOS I/O errors (tc) *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* - 08 Jan 93: Added environment-son, pcs-learn-symbols... (mv) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
-
- ; The following definitions are used only at compile time for readability
- ; and understanding. They will not be written out to the .so file.
- ; See miniboot.s and compile.all.
-
- (compile-time-alias IO-ERRORS-START 21)
- (compile-time-alias IO-ERRORS-END 108)
- (compile-time-alias DOS-IO-ERROR 21)
- (compile-time-alias FILE-NOT-FOUND 22)
- (compile-time-alias PATH-NOT-FOUND 23)
- (compile-time-alias TOO-MANY-FILES 24)
-
- (define assert-procedure)
- (define breakpoint-procedure)
- (define error-procedure)
- (define *error-handler*)
-
- (letrec
- ((uv-msg
- '(1 2 3 4))
- (msg-codes
- '((0 . "Unspecified VM error")
- (1 . "Variable not defined in current environment")
- (2 . "SET! of an unbound variable")
- (3 . "Variable not defined in lexical environment")
- (4 . "SET! of an unbound lexical variable")
- (5 . "Variable not defined in fluid environment")
- (6 . "SET-FLUID! of an unbound fluid variable")
- (7 . "Vector index out of range")
- (8 . "String index out of range")
- (9 . "Invalid substring range") ; not generated
- (10 . "Invalid operand to VM instruction")
- (11 . "User keyboard interrupt")
- (12 . "Attempt to call a non-procedural object")
- ;; (13 . "Engine Timer Interrupt")
- (14 . "I/O attempted to a de-exposed window")
- ;; 14 is a trap for a window handler, not a real error
- (15 . "FLONUM overflow or underflow")
- (16 . "Divide by zero")
- (17 . "Non-numeric operand to arithmetic operation")
- (18 . "Register overflow--Too many arguments to closure")
- (19 . "MAKE-VECTOR size limit exceeded")
- (20 . "MAKE-STRING size limit exceeded")
- (21 . "DOS I/O error number ")
- (22 . "DOS I/O error - File not found")
- (23 . "DOS I/O error - Path not found")
- (24 . "DOS I/O error - Too many open files")
- (25 . "DOS I/O error - Access denied")
- (32 . "DOS I/O error - Invalid access")
- (36 . "DOS I/O error - Invalid disk drive")
- (39 . "DOS I/O error - Disk write protected")
- (41 . "DOS I/O error - Drive not ready")
- (48 . "DOS I/O error - Printer out of paper")
- (200 . "DOS I/O error - Disk Full")
- ))
- (oops
- (lambda (msg irritant env stk-index kind error-code)
- (fluid-let ((input-port standard-input)
- (output-port standard-output))
- (let* ((si (if (negative? stk-index)
- (%reify-stack (+ (%reify-stack -1) 6))
- stk-index))
- (env (if (null? env)
- (%reify-stack (+ si 9))
- env)))
- (newline)
- (display kind)
- (when msg (display msg))
- (newline)
- (write irritant)
- (newline)
- (pcs-kill-engine)
-
- (if (unbound? compile)
- ;; see if compiler auto-loadable
- (when (not (pcs-autoload-binding 'compile))
- ;; Cant find compiler, punt
- (display (integer->char 7)) ;beep
- (display "Press a key to return to toplevel, escape to exit to DOS")
- (let ((ch (read-char)))
- (if (char=? ch #\escape)
- (exit)
- (scheme-reset))))
- ;else
- (if (null? (%env-lu '%inspector user-initial-environment))
- ;; check to see if we can load the inspector
- (when (or (eqv? *error-message* TOO-MANY-FILES)
- (null? (pcs-autoload-binding '%inspector)))
- (display "Unable to autoload the inspector - file INSPECT.FSL")
- (reset))))
-
- (%inspector msg kind irritant env si error-code)
-
- ))))
- (envoke-handler
- (lambda (number msg irritant stk-index err-code)
- (let ((handler (lambda ()
- (oops msg
- irritant
- '()
- stk-index
- "[VM ERROR encountered!] "
- err-code))))
- (if (closure? *user-error-handler*)
- (*user-error-handler* number
- msg
- irritant
- handler)
- (handler)))))
- (decipher-error
- (lambda (stk-index)
- (let ((err-code *error-code*)
- (irritant *irritant*)
- (err-num (and (number? *error-message*) *error-message*))
- (msg (apply-if (assv *error-message* msg-codes)
- cdr
- *error-message*)))
- (cond ((eqv? err-num 11) ; Shift Break
- (set! err-num 100))
- ((and (eqv? err-num 10) ; BGI graphics errors
- (eqv? (car irritant) '%graphics))
- (if (or (unbound? *pcs-bgi-error*)
- (unbound? *pcs-graphics-error*))
- (set! msg "Unidentified BGI error - *PCS-BGI/GRAPHICS-ERROR* undefined")
- (let ((graph-msg (*pcs-bgi-error*)))
- (when (not (string-ci=? "No error" graph-msg))
- (set! msg graph-msg)
- (set! irritant *pcs-graphics-error*)))))
- ((and err-num ; I/O Errors
- (>= err-num IO-ERRORS-START)
- (<= err-num IO-ERRORS-END))
- (if (and (or (= err-num FILE-NOT-FOUND)
- (= err-num PATH-NOT-FOUND))
- (fluid-bound? *file-exists-open*))
- ((fluid *file-exists-open*) #F)) ; error continuation
-
- (set! err-num (- err-num (-1+ DOS-IO-ERROR)))
- (if (number? msg)
- (set! msg (string-append (cdr (assv DOS-IO-ERROR msg-codes))
- (integer->string err-num 10))))))
- (envoke-handler err-num msg irritant stk-index err-code))))
- ) ; letrec vars
-
- (begin
- (set! assert-procedure ; ASSERT-PROCEDURE
- (lambda (msgs env)
- (oops '() (cons 'ASSERT (cons '() msgs)) env -1 "[ASSERT failure!] " 0)))
-
- (set! breakpoint-procedure ; BREAKPOINT-PROCEDURE
- (lambda (msg irritant env . rest)
- (let* ((stk-index (if (or (null? rest)
- (not (integer? (car rest))))
- -1
- (car rest))))
- (oops msg irritant env stk-index "[BKPT encountered!] " 0))))
-
- (set! error-procedure ; ERROR-PROCEDURE
- (lambda (msg irritant env)
- (let ((system-error-handler
- (lambda ()
- (oops msg irritant env -1 "[ERROR encountered!] " 0))))
- (if (closure? *user-error-handler*)
- (begin
- (*user-error-handler* '() msg irritant system-error-handler))
- ;else
- (system-error-handler)))))
-
- (set! *error-handler* ; *ERROR-HANDLER*
- (lambda ()
- (cond ((eqv? *error-message* 13) ; special: TIMEOUT_CONDITION
- (if *irritant*
- (mouse 'TRIGGER *irritant*)
- (pcs-engine-timeout)))
- ((and (zero? *error-code*) ; resumable
- (memv *error-message* uv-msg)) ; unbound symbol
- (if (pcs-autoload-binding *irritant*)
- '() ; autoload worked!
- ;else
- (let ((info (getprop *irritant* 'PCS*PRIMOP-HANDLER))
- (compiler-present (or (not (unbound? compile))
- (pcs-autoload-binding 'compile))))
- (cond ((and compiler-present
- (integer? info)
- (getprop *irritant* 'PCS*OPCODE))
- (let* ((vars '(J I H G F E D C B A))
- (bvl (list-tail vars (- (length vars) info)))
- (form `(define ,*irritant*
- (lambda ,bvl
- (,*irritant* . ,bvl))))
- (dw pcs-display-warnings)
- (ip pcs-integrate-primitives))
- (set! pcs-display-warnings #F)
- (set! pcs-integrate-primitives #T)
- (eval form user-global-environment)
- (set! pcs-display-warnings dw)
- (set! pcs-integrate-primitives ip)
- '()))
- ((and compiler-present
- (pair? info)
- (eq? (car info) 'DEFINE-INTEGRABLE))
- (let ((form `(define ,*irritant* ,(cdr info)))
- (dw pcs-display-warnings)
- (ip pcs-integrate-primitives))
- (set! pcs-display-warnings #F)
- (set! pcs-integrate-primitives #T)
- (eval form user-initial-environment)
- (set! pcs-display-warnings dw)
- (set! pcs-integrate-primitives ip)
- '()))
- (else
- (set! *error-message*
- (cdr (assv *error-message* msg-codes)))
- (*error-handler*))))))
- (else
- (decipher-error (%reify-stack
- (+ (%reify-stack
- (+ (%reify-stack -1) 6)) 6)))))
- ) ;lambda
- ) ;set!
- ) ;begin
- ) ;letrec
-
- ; autoload infos routines are defined in this file since
- ; they are very connected to the error handler.
-
- (define autoload-from-file ; AUTOLOAD-FROM-FILE
- (lambda (file names . rest)
- (let ((env (if rest (car rest) user-initial-environment)))
- (putprop 'PCS-AUTOLOAD-INFO
- (cons (list file names env)
- (getprop 'PCS-AUTOLOAD-INFO
- 'PCS-AUTOLOAD-INFO))
- 'PCS-AUTOLOAD-INFO)
- (pcs-learn-symbols names)
- '())))
-
-
-
- (define pcs-autoload-binding '()) ; PCS-AUTOLOAD-BINDING
- (define remove-autoload-info '()) ; REMOVE-AUTOLOAD-INFO
-
- (letrec
- ((find-entry
- (lambda (name info)
- (and info
- (or (symbol? name) (string? name))
- (find-item name (caar info)(cadar info) info))))
- (find-item
- (lambda (name file symbols info)
- (cond ((string? name)
- (if (string-ci=? name file)
- (car info)
- (find-entry name (cdr info))))
- ((null? symbols)
- (find-entry name (cdr info)))
- ((eq? name (car symbols))
- (car info))
- (else
- (find-item name file (cdr symbols) info))))))
- (set! pcs-autoload-binding
- (lambda (name)
- (let* ((info (getprop 'PCS-AUTOLOAD-INFO 'PCS-AUTOLOAD-INFO))
- (entry (find-entry name info)))
- (and entry
- (let ((file (car entry))
- (env (caddr entry)))
- (and (string? file)
- (file-exists? file)
- (let ((saved-env (%set-global-environment env)))
- (load file)
- (%set-global-environment saved-env)
- (not (null? (%env-lu name env)))
- )))))))
- (set! remove-autoload-info
- (lambda (filename)
- (let* ((info (getprop 'PCS-AUTOLOAD-INFO 'PCS-AUTOLOAD-INFO))
- (entry (find-entry (%system-file-name filename) info)))
- (and entry
- (putprop 'PCS-AUTOLOAD-INFO
- (delq! entry
- (getprop 'PCS-AUTOLOAD-INFO
- 'PCS-AUTOLOAD-INFO))
- 'PCS-AUTOLOAD-INFO)))))
- )
-
- (define environment-bindings ; ENVIRONMENT-BINDINGS
- (letrec
- ((linked-bindings
- (lambda (a-list names values)
- (if (null? names)
- (%reverse! a-list)
- (linked-bindings (cons (cons (car names)(cdr values))
- a-list)
- (cdr names)
- (car values)))))
- (hashed-bindings
- (lambda (a-list index env)
- (if (zero? index)
- a-list
- (let ((bucket (%reify env index)))
- (hashed-bindings (if (null? bucket)
- a-list
- (bucket-bindings a-list bucket))
- (- index 1)
- env)))))
- (bucket-bindings
- (lambda (a-list bucket)
- (if (null? bucket)
- a-list
- (bucket-bindings (cons (car bucket) a-list)
- (cdr bucket))))))
- (lambda (obj)
- (if (null? obj)
- obj
- (let* ((env (cond ((environment? obj) ; environment?
- obj)
- ((or (closure? obj) ; closure?
- (delayed-object? obj)) ; delayed object?
- (procedure-environment obj))
- (else
- (%error-invalid-operand 'ENVIRONMENT-BINDINGS
- obj))))
- (size (%reify env -1)))
- (if (= size 12)
- (linked-bindings '() (%reify env 1) (%reify env 2))
- (hashed-bindings '() (- (quotient size 3) 2) env)))))))
-
-
- ;
- ; UNBIND is a function which will remove a variable's binding from a given
- ; environment. It will work for either of the 2 global environments
- ; (USER-GLOBAL-ENVIRONMENT and USER-INITIAL-ENVIRONMENT) or for any other
- ; heap allocated environments. Removing the binding from the environment
- ; will allow the garbage collector to reclaim that space. Also, once
- ; unbound, the autoloader may reload the variable whenever that variable
- ; is referenced again.
- ;
-
-
- (define unbind
- (letrec
- ((remove-hashed-binding!
- (lambda (key alist)
- (cond ((null? (cadr alist))
- '())
- ((eq? key (caadr alist))
- (set-cdr! alist (cddr alist)))
- (else
- (remove-hashed-binding! key (cdr alist))))))
-
- (modify-hashed-env!
- (lambda (symbol env)
- (let* ((hash-val (1+ (%esc 9 (symbol->string symbol))))
- (sym-list (%reify env hash-val)))
-
- (if (null? sym-list)
- '()
- ;else
- (begin
- (if (eq? symbol (caar sym-list))
- (set! sym-list (cdr sym-list))
- ;else
- (remove-hashed-binding! symbol sym-list))
- (%reify! env hash-val sym-list)
- env)))))
-
- (remove-linked-binding!
- (lambda (key names values)
- (cond ((null? (cadr names))
- '())
- ((eq? key (cadr names))
- (set-cdr! names (cddr names))
- (set-car! values (caar values)))
- (else
- (remove-linked-binding! key (cdr names) (car values))))))
-
- (modify-linked-env!
- (lambda (symbol env names values)
- (if (eq? symbol (car names))
- (begin
- (set! names (cdr names))
- (set! values (car values)))
- ;else
- (remove-linked-binding! symbol names values))
- (%reify! env 1 names)
- (%reify! env 2 values)))
- )
-
- (lambda (symbol env)
- (cond ((not (symbol? symbol))
- (%error-invalid-operand 'UNBIND symbol))
- ((not (environment? env))
- (%error-invalid-operand 'UNBIND env))
- (else
- (if (= (%reify env -1) 12)
- (modify-linked-env! symbol env (%reify env 1) (%reify env 2))
- ;
- (modify-hashed-env! symbol env)))))))
-
-
- (define (procedure-environment obj) ; PROCEDURE-ENVIRONMENT
- (cond ((closure? obj)
- (%reify obj 1))
- ((delayed-object? obj)
- (procedure-environment (vector-ref obj 1)))
- (else
- (%error-invalid-operand 'PROCEDURE-ENVIRONMENT obj))))
-
- (define environment-son ; ENVIRONMENT-SON
- (let ((code-block (compile '(make-environment (define obj)))))
- (lambda (env)
- (if (environment? env)
- (let* ((saved-env (%set-global-environment env))
- (result (%execute code-block)))
- (%set-global-environment saved-env)
- (unbind 'obj result)
- result)
- (%error-invalid-operand 'ENVIRONMENT-SON env)))))
-
- ; PCS-KNOWN-SYMBOLS-ENVIRONMENT, involved for tab completion,
- ; is defined here to recognize auto-loadable symbols.
-
- (define pcs-known-symbols-environment ; PCS-KNOWN-SYMBOLS-ENVIRONMENT
- (environment-son pcs-reserved-symbols-environment))
-
- ; The following is an adaptative procedure: if the compiled
- ; form is recognized (it should be), it is just "patched", which is much
- ; faster than evaluating the whole expression hundreds of times
- ; when PCS starts up. Test is performed only during fast-load
- ; of this module, of course. (mv)
-
- (define pcs-learn-symbols ; PCS-LEARN-SYMBOLS
- (let* ((code (compile '(set! (access XXX pcs-known-symbols-environment) ())))
- (sym (last-pair (cadddr code)))
- (proc
- (if (eq? (car sym) 'XXX)
- (lambda (name)
- (set-car! sym name)
- (%execute code))
- (lambda (name)
- (eval `(set! (access ,name pcs-known-symbols-environment) ()))))))
- (lambda (names)
- (for-each proc names))))
-
- ; The following closure allows scheme use of incremental symbol lookup
-
- (define pcs-recognize-symbol ; PCS-RECOGNIZE-SYMBOL
- (lambda (str . len)
- (set! len (car len))
- (cond ((eq? str 'done) (%esc 35 -1))
- ((and (string? str) (number? len) (>= len 0) (<= len (string-length str)))
- (%esc 35 str len))
- (else (%error-invalid-operand-list 'pcs-recognize-symbol str len)))))